# -*- coding: utf-8 -*-
"""
学习打卡控制器
目的：处理学习打卡相关的HTTP请求，提供RESTful API接口
职责：接收请求参数、调用服务层、返回HTTP响应
"""
from flask import Blueprint, request
from datetime import datetime, date
from app.services.study_service import StudyService
from app.utils.auth import token_required, get_current_user
from app.utils.response import bad_request_response, internal_error_response
from app.dto.study_dto import (
    CreateSubjectRequest, UpdateSubjectRequest,
    CheckInRequest, UpdateCheckInRequest,
    GetCheckInsListRequest, GetStatisticsRequest, GetCalendarRequest
)

# 创建蓝图对象，URL前缀为 /api/study
study_bp = Blueprint('study', __name__, url_prefix='/api/study')


# ==================== 科目管理接口 ====================

@study_bp.route('/subjects', methods=['POST'])
@token_required
def create_subject():
    """
    创建学习科目API

    请求方法：POST
    认证：需要
    URL：/api/study/subjects

    Request Body:
    {
        "name": "科目名称",
        "description": "科目描述（可选）",
        "icon": "图标路径（可选）",
        "color": "颜色代码（可选，默认#1890ff）",
        "target_days": 100,  # 目标打卡天数（可选，默认0）
        "is_public": 0,  # 是否公开（可选，默认0）
        "sort_order": 0  # 排序顺序（可选，默认0）
    }

    Response:
    {
        "code": 200,
        "message": "科目创建成功",
        "data": {科目信息}
    }
    """
    try:
        # 获取当前登录用户对象，然后提取用户ID
        current_user = get_current_user()
        user_id = current_user.id if current_user else None

        if not user_id:
            return bad_request_response('用户认证失败')

        # 获取请求数据
        data = request.get_json()
        if not data:
            return bad_request_response('请求数据格式错误')

        # 封装为DTO对象
        req = CreateSubjectRequest(
            user_id=user_id,
            name=data.get('name'),
            description=data.get('description'),
            icon=data.get('icon'),
            color=data.get('color', '#1890ff'),
            target_days=data.get('target_days', 0),
            is_public=data.get('is_public', 0),
            sort_order=data.get('sort_order', 0)
        )

        # 调用服务层
        result = StudyService.create_subject(req)
        return result.to_response()

    except Exception as e:
        return internal_error_response(f'服务器错误：{str(e)}')


@study_bp.route('/subjects/<int:subject_id>', methods=['PUT'])
@token_required
def update_subject(subject_id):
    """
    更新学习科目API

    请求方法：PUT
    认证：需要
    URL：/api/study/subjects/{id}

    Request Body（所有字段可选，只更新提供的字段）:
    {
        "name": "新名称",
        "description": "新描述",
        "icon": "新图标",
        "color": "新颜色",
        "target_days": 200,
        "is_public": 1,
        "sort_order": 1,
        "status": 1
    }

    Response:
    {
        "code": 200,
        "message": "科目更新成功",
        "data": {科目信息}
    }
    """
    try:
        current_user = get_current_user()
        user_id = current_user.id if current_user else None

        if not user_id:
            return bad_request_response('用户认证失败')

        data = request.get_json()

        if not data:
            return bad_request_response('请求数据格式错误')

        # 封装为DTO对象
        req = UpdateSubjectRequest(
            subject_id=subject_id,
            user_id=user_id,
            name=data.get('name'),
            description=data.get('description'),
            icon=data.get('icon'),
            color=data.get('color'),
            target_days=data.get('target_days'),
            is_public=data.get('is_public'),
            sort_order=data.get('sort_order'),
            status=data.get('status')
        )

        result = StudyService.update_subject(req)
        return result.to_response()

    except Exception as e:
        return internal_error_response(f'服务器错误：{str(e)}')


@study_bp.route('/subjects/<int:subject_id>', methods=['DELETE'])
@token_required
def delete_subject(subject_id):
    """
    删除学习科目API（软删除）

    请求方法：DELETE
    认证：需要
    URL：/api/study/subjects/{id}

    Response:
    {
        "code": 200,
        "message": "科目删除成功"
    }
    """
    try:
        current_user = get_current_user()
        user_id = current_user.id if current_user else None

        if not user_id:
            return bad_request_response('用户认证失败')

        result = StudyService.delete_subject(subject_id, user_id)
        return result.to_response()

    except Exception as e:
        return internal_error_response(f'服务器错误：{str(e)}')


@study_bp.route('/subjects/<int:subject_id>', methods=['GET'])
@token_required
def get_subject(subject_id):
    """
    获取科目详情API

    请求方法：GET
    认证：需要
    URL：/api/study/subjects/{id}

    Response:
    {
        "code": 200,
        "message": "操作成功",
        "data": {科目信息}
    }
    """
    try:
        current_user = get_current_user()
        user_id = current_user.id if current_user else None

        if not user_id:
            return bad_request_response('用户认证失败')

        result = StudyService.get_subject_by_id(subject_id, user_id)
        return result.to_response()

    except Exception as e:
        return internal_error_response(f'服务器错误：{str(e)}')


@study_bp.route('/subjects', methods=['GET'])
@token_required
def get_subjects_list():
    """
    获取科目列表API

    请求方法：GET
    认证：需要
    URL：/api/study/subjects

    Query Parameters:
    - include_public: 是否包含公开科目（可选，默认false）

    Response:
    {
        "code": 200,
        "message": "操作成功",
        "data": [{科目信息列表}]
    }
    """
    try:
        current_user = get_current_user()
        user_id = current_user.id if current_user else None

        if not user_id:
            return bad_request_response('用户认证失败')

        include_public = request.args.get('include_public', 'false').lower() == 'true'

        result = StudyService.get_subjects_list(user_id, include_public)
        return result.to_response()

    except Exception as e:
        return internal_error_response(f'服务器错误：{str(e)}')


# ==================== 打卡记录接口 ====================

@study_bp.route('/check-in', methods=['POST'])
@token_required
def check_in():
    """
    每日打卡API

    请求方法：POST
    认证：需要
    URL：/api/study/check-in

    Request Body:
    {
        "subject_id": 1,  # 科目ID（必填）
        "check_in_date": "2025-10-08",  # 打卡日期（必填，格式YYYY-MM-DD）
        "duration_minutes": 60,  # 学习时长（可选）
        "content": "学习笔记内容",  # 打卡笔记（可选）
        "mood": 5,  # 学习心情1-5（可选）
        "location_id": 1,  # 地点ID（可选）
        "images": ["path1.jpg", "path2.jpg"]  # 图片路径数组（可选）
    }

    Response:
    {
        "code": 200,
        "message": "打卡成功",
        "data": {打卡记录信息}
    }
    """
    try:
        current_user = get_current_user()
        user_id = current_user.id if current_user else None

        if not user_id:
            return bad_request_response('用户认证失败')

        data = request.get_json()

        if not data:
            return bad_request_response('请求数据格式错误')

        # 验证必填字段
        if not data.get('subject_id') or not data.get('check_in_date'):
            return bad_request_response('科目ID和打卡日期为必填项')

        # 解析日期并进行时区验证
        try:
            check_in_date = datetime.strptime(data.get('check_in_date'), '%Y-%m-%d').date()

            # 验证打卡日期不能是未来日期（使用数据库时间确保时区正确）
            from app.utils.datetime_utils import get_db_now
            db_now = get_db_now()
            today = db_now.date()

            # 添加调试信息
            print(f"[DEBUG] 前端传入日期: {check_in_date}, 数据库当前日期: {today}")

            if check_in_date > today:
                return bad_request_response('打卡日期不能是未来日期')

        except ValueError:
            return bad_request_response('日期格式错误，应为YYYY-MM-DD')

        # 封装为DTO对象
        req = CheckInRequest(
            user_id=user_id,
            subject_id=data.get('subject_id'),
            check_in_date=check_in_date,
            duration_minutes=data.get('duration_minutes'),
            content=data.get('content'),
            mood=data.get('mood'),
            location_id=data.get('location_id'),
            images=data.get('images')
        )

        result = StudyService.check_in(req)
        return result.to_response()

    except Exception as e:
        return internal_error_response(f'服务器错误：{str(e)}')


@study_bp.route('/check-ins/<int:check_in_id>', methods=['PUT'])
@token_required
def update_check_in(check_in_id):
    """
    更新打卡记录API

    请求方法：PUT
    认证：需要
    URL：/api/study/check-ins/{id}

    Request Body（所有字段可选）:
    {
        "duration_minutes": 90,
        "content": "更新后的笔记",
        "mood": 4,
        "location_id": 2,
        "images": ["new_path.jpg"]
    }

    Response:
    {
        "code": 200,
        "message": "打卡记录更新成功",
        "data": {打卡记录信息}
    }
    """
    try:
        current_user = get_current_user()
        user_id = current_user.id if current_user else None

        if not user_id:
            return bad_request_response('用户认证失败')

        data = request.get_json()

        if not data:
            return bad_request_response('请求数据格式错误')

        # 封装为DTO对象
        req = UpdateCheckInRequest(
            check_in_id=check_in_id,
            user_id=user_id,
            duration_minutes=data.get('duration_minutes'),
            content=data.get('content'),
            mood=data.get('mood'),
            location_id=data.get('location_id'),
            images=data.get('images')
        )

        result = StudyService.update_check_in(req)
        return result.to_response()

    except Exception as e:
        return internal_error_response(f'服务器错误：{str(e)}')


@study_bp.route('/check-ins/<int:check_in_id>', methods=['DELETE'])
@token_required
def delete_check_in(check_in_id):
    """
    删除打卡记录API（软删除）

    请求方法：DELETE
    认证：需要
    URL：/api/study/check-ins/{id}

    Response:
    {
        "code": 200,
        "message": "打卡记录删除成功"
    }
    """
    try:
        current_user = get_current_user()
        user_id = current_user.id if current_user else None

        if not user_id:
            return bad_request_response('用户认证失败')

        result = StudyService.delete_check_in(check_in_id, user_id)
        return result.to_response()

    except Exception as e:
        return internal_error_response(f'服务器错误：{str(e)}')


@study_bp.route('/check-ins/<int:check_in_id>', methods=['GET'])
@token_required
def get_check_in(check_in_id):
    """
    获取打卡记录详情API

    请求方法：GET
    认证：需要
    URL：/api/study/check-ins/{id}

    Response:
    {
        "code": 200,
        "message": "操作成功",
        "data": {打卡记录详细信息}
    }
    """
    try:
        current_user = get_current_user()
        user_id = current_user.id if current_user else None

        if not user_id:
            return bad_request_response('用户认证失败')

        result = StudyService.get_check_in_by_id(check_in_id, user_id)
        return result.to_response()

    except Exception as e:
        return internal_error_response(f'服务器错误：{str(e)}')


@study_bp.route('/check-ins', methods=['GET'])
@token_required
def get_check_ins_list():
    """
    获取打卡记录列表API（分页）

    请求方法：GET
    认证：需要
    URL：/api/study/check-ins

    Query Parameters:
    - page: 页码（可选，默认1）
    - page_size: 每页数量（可选，默认10，最大100）
    - subject_id: 科目ID筛选（可选）
    - start_date: 开始日期筛选（可选，格式YYYY-MM-DD）
    - end_date: 结束日期筛选（可选，格式YYYY-MM-DD）
    - mood: 心情筛选（可选，1-5）
    - status: 状态筛选（可选，0-已删除，1-正常，默认1）

    Response:
    {
        "code": 200,
        "message": "操作成功",
        "data": {
            "items": [{打卡记录列表}],
            "total": 100,
            "page": 1,
            "page_size": 10,
            "total_pages": 10
        }
    }
    """
    try:
        current_user = get_current_user()
        user_id = current_user.id if current_user else None

        if not user_id:
            return bad_request_response('用户认证失败')

        # 解析查询参数
        page = int(request.args.get('page', 1))
        page_size = int(request.args.get('page_size', 10))
        subject_id = request.args.get('subject_id', type=int)
        mood = request.args.get('mood', type=int)
        status = int(request.args.get('status', 1))

        # 解析日期参数
        start_date = None
        end_date = None
        if request.args.get('start_date'):
            try:
                start_date = datetime.strptime(request.args.get('start_date'), '%Y-%m-%d').date()
            except ValueError:
                return bad_request_response('开始日期格式错误，应为YYYY-MM-DD')

        if request.args.get('end_date'):
            try:
                end_date = datetime.strptime(request.args.get('end_date'), '%Y-%m-%d').date()
            except ValueError:
                return bad_request_response('结束日期格式错误，应为YYYY-MM-DD')

        # 封装为DTO对象
        req = GetCheckInsListRequest(
            user_id=user_id,
            page=page,
            page_size=page_size,
            subject_id=subject_id,
            start_date=start_date,
            end_date=end_date,
            mood=mood,
            status=status
        )

        result = StudyService.get_check_ins_list(req)
        return result.to_response()

    except ValueError as e:
        return bad_request_response(f'参数错误：{str(e)}')
    except Exception as e:
        return internal_error_response(f'服务器错误：{str(e)}')


# ==================== 统计接口 ====================

@study_bp.route('/statistics/summary', methods=['GET'])
@token_required
def get_statistics_summary():
    """
    获取统计汇总数据API

    请求方法：GET
    认证：需要
    URL：/api/study/statistics/summary

    Query Parameters:
    - subject_id: 科目ID（可选，不传则统计全部科目）

    Response:
    {
        "code": 200,
        "message": "操作成功",
        "data": {
            "total_days": 100,  # 总打卡天数
            "total_duration": 6000,  # 总学习时长（分钟）
            "continuous_days": 7,  # 当前连续打卡天数
            "max_continuous_days": 30,  # 最大连续打卡天数
            "week_days": 5,  # 本周打卡天数
            "month_days": 20  # 本月打卡天数
        }
    }
    """
    try:
        current_user = get_current_user()
        user_id = current_user.id if current_user else None

        if not user_id:
            return bad_request_response('用户认证失败')

        subject_id = request.args.get('subject_id', type=int)

        result = StudyService.get_statistics_summary(user_id, subject_id)
        return result.to_response()

    except Exception as e:
        return internal_error_response(f'服务器错误：{str(e)}')


@study_bp.route('/statistics/calendar', methods=['GET'])
@token_required
def get_calendar_data():
    """
    获取日历热力图数据API

    请求方法：GET
    认证：需要
    URL：/api/study/statistics/calendar

    Query Parameters:
    - year: 年份（必填）
    - month: 月份（可选，不传则查询整年）
    - subject_id: 科目ID（可选，不传则查询全部科目）

    Response:
    {
        "code": 200,
        "message": "操作成功",
        "data": [
            {
                "date": "2025-10-08",
                "count": 2,  # 打卡次数
                "duration": 120  # 学习时长
            },
            ...
        ]
    }
    """
    try:
        current_user = get_current_user()
        user_id = current_user.id if current_user else None

        if not user_id:
            return bad_request_response('用户认证失败')

        # 验证必填参数
        year = request.args.get('year', type=int)
        if not year:
            return bad_request_response('年份参数year为必填项')

        month = request.args.get('month', type=int)
        subject_id = request.args.get('subject_id', type=int)

        # 封装为DTO对象
        req = GetCalendarRequest(
            user_id=user_id,
            year=year,
            month=month,
            subject_id=subject_id
        )

        result = StudyService.get_calendar_data(req)
        return result.to_response()

    except ValueError as e:
        return bad_request_response(f'参数错误：{str(e)}')
    except Exception as e:
        return internal_error_response(f'服务器错误：{str(e)}')
